home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 033a / aed244a.zip / ANSIED-3.BAS < prev    next >
BASIC Source File  |  1991-02-16  |  43KB  |  1,290 lines

  1. '*
  2. '*  ANSIED v2.44a
  3. '*---------------------------------------------------------------------------
  4. '*  Full Screen Text Editor for RBBS-PC
  5. '*  QuickBASIC v3.0 Version
  6. '*  02-16-91
  7. '*
  8. '*  v2.1xx ... made it work with RBBS v17
  9. '*  v2.2 ..... fixed some inconsistincies in the code as to # of lines in msg.
  10. '*             Some of the code thought 99 was length, some thought 100.
  11. '*  v2.3 ..... let it work with quoted reply.  No more REDIM of ZOutTxt$
  12. '*  v2.4 ..... removed tabs, margins code to be smaller
  13. '*  v2.41..... fixed bug with loss of bold attribute occasionally
  14. '*  v2.42..... made it work as a v17.3 subroutine.  Added block delete.
  15. '*  v2.43..... Added to: and from:.  Made cursor keys work locally.
  16. '*  v2.43a.... Stupid little bugs fixed
  17. '*  v2.44..... Fixed bugs, added ^T, Import, Subject, ASM functions
  18. '*  v2.44a.... Wordwrap/reflow bug fixed.  Arrows work in del.  Lines renum.
  19. '*
  20. '*  Returns:
  21. '*  ZSubParm  =  1 - Save Message
  22. '*            =  2 - Abort Message
  23. '*            = -1 - Dropped Carrier
  24. '*            = -2 - Sleep Disconnect
  25. '*
  26. '*
  27.  
  28. ' $INCLUDE: 'RBBS-VAR.MOD'
  29.  
  30. 100   CONST RedFore = 31
  31.       CONST GreenFore = 32
  32.       CONST YellowFore = 33
  33.       CONST BlueFore = 34
  34.       CONST MagentaFore = 35
  35.       CONST CyanFore = 36
  36.       CONST WhiteFore = 37
  37.       CONST BlueBack = 44
  38.       CONST DefaultColor = 99
  39.       CONST DefaultBold = 99
  40.  
  41. 110   CONST ESCKey = 27
  42.       CONST BackspKey = 8
  43.       CONST OtherBackspKey = 127
  44.       CONST CarrRet = 13
  45.       CONST WordLeftKey = 1          ' Ctrl-A
  46.       CONST ReformTextKey = 2        ' Ctrl-B
  47.       CONST PageDownKey = 3          ' Ctrl-C
  48.       CONST ColRightKey = 4          ' Ctrl-D
  49.       CONST LineUpKey = 5            ' Ctrl-E
  50.       CONST WordRightKey = 6         ' Ctrl-F
  51.       CONST CharDeleteKey = 7        ' Ctrl-G
  52.       CONST EndSessionKey = 11       ' Ctrl-K
  53.       CONST HelpKey = 14             ' Ctrl-N
  54.       CONST ReflowTextKey = 15       ' Ctrl-O
  55.       CONST RepaintKey = 16          ' Ctrl-P
  56.       CONST PageUpKey = 18           ' Ctrl-R
  57.       CONST ColLeftKey = 19          ' Ctrl-S
  58.       CONST DeleteWordRightKey = 20  ' Ctrl-T
  59.       CONST ToggleINSKey = 22        ' Ctrl-V
  60.       CONST HomeKey = 23             ' Ctrl-W
  61.       CONST LineDownKey = 24         ' Ctrl-X
  62.       CONST LineDeleteKey = 25       ' Ctrl-Y
  63.       CONST EndKey = 26              ' Ctrl-Z
  64.  
  65.       CONST BlankLine$ = ""
  66. 119   CONST Version$ = "v2.44a"      ' v2.44a
  67.  
  68.       DEFINT A-Z
  69.  
  70. 120   COMMON SHARED /Ansied/ CurrentRow, CurrentCol, TopLine
  71.       COMMON SHARED /Ansied/ OldColour, IsBold, InsertMode
  72.       COMMON SHARED /Ansied/ SoftSpace$
  73.       COMMON SHARED /Ansied/ BlockDelActive, MsgLockLines
  74.       COMMON SHARED /Ansied/ BlockLine1, BlockLine2
  75.       COMMON SHARED /Ansied/ MsgTo$, MsgSubj$
  76.  
  77. '*  AnsiEd
  78. '*----------------------------------------------------------------------------
  79. '*  Main full-screen editor routine
  80. '*
  81. '*
  82.       SUB Ansied (T$, S$, L%) STATIC
  83.  
  84.       '*
  85.       '* ZworkAra$() holds what's currently on the user's screen.
  86.       '* 24 Lines: ZWorkAra$(1) = Menu, Bottom Line = "Line 25"
  87.       '*
  88. 500   REDIM ZWorkAra$(24)
  89.       '*
  90.       '* TopLine is the index into the ZOutTxt$() array that
  91.       '* corresponds to the top of the displayed image, i.e.
  92.       '* what's on line 3 of the user's screen.
  93.       '*
  94.       '*   1,12,23,34,45,56,78
  95.       '*
  96.       TopLine = 1
  97.       SoftSpace$ = CHR$(250)
  98.       InsertMode = ZTrue
  99.       ZLineFeed$ = CHR$(10)
  100.       BlockDelActive = ZFalse
  101.       HiLiteSave = ZHiLiteOff
  102.       ZHiLiteOff = ZFalse
  103.       UseTputSave = ZUseTput
  104.       ZUseTput = ZFalse
  105.  
  106.       MsgLockLines = L
  107.  
  108.       MsgTo$ = T$
  109.       CALL NameCaps(MsgTo$)
  110.  
  111.       MsgSubj$ = S$
  112.       YY$ = ""
  113.       IF LEFT$(MsgSubj$, 3) = "(R)" THEN
  114.          YY$ = "(R)"
  115.          MsgSubj$ = MID$(MsgSubj$, 4)
  116.       END IF
  117.       CALL NameCaps(MsgSubj$)
  118.       MsgSubj$ = YY$ + MsgSubj$
  119.  
  120.       '*
  121.       '* Initialize the screen
  122.       '*
  123. 510   CALL ClearScreen
  124.       CALL UpdateStatusLine(1)
  125.       CALL MoveCursor(3, 1)
  126.       '*
  127.       '* Remove ANSI sequences from the quoted lines
  128.       '*
  129.       IF ZLinesInMsg > 88 THEN
  130.          ZLinesInMsg = 88
  131.       END IF
  132.       IF ZMaxMsgLines > 98 THEN
  133.          ZMaxMsgLines = 98
  134.       END IF
  135.       IF ZLinesInMsg > ZMaxMsgLines THEN
  136.          ZLinesInMsg = ZMaxMsgLines
  137.       END IF
  138.       FOR I = ZLinesInMsg + 1 TO 99
  139.          ZOutTxt$(I) = BlankLine$
  140.       NEXT
  141.       IF ZLinesInMsg <> 0 THEN
  142.          FOR I = 1 TO ZLinesInMsg
  143.             CALL UnString(ZOutTxt$(I), "")
  144.          NEXT
  145.          J = ZLinesInMsg \ 11
  146.          IF ZLinesInMsg MOD 11 = 0 THEN
  147.            J = J - 1
  148.          END IF
  149.          TopLine = J * 11 + 1
  150.          J = ZLinesInMsg - TopLine
  151.          CALL MoveCursor(J + 5, 1)
  152.       END IF
  153.       CALL UpdateScreen
  154.  
  155.       '*
  156.       '* Run the Editor
  157.       '*
  158. 520   WHILE 1
  159.  
  160.          CALL GetChar(B$): GOSUB 740
  161.          KeyPressed = ASC(B$)
  162.          CALL SaveCursor(RowSave, ColSave)
  163.  
  164.          '*
  165.          '* Look for an ANSI escape sequence after an ESC
  166.          '*
  167. 525      IF KeyPressed = ESCKey THEN            ' v2.44a
  168.             CALL GetChar(B$): GOSUB 740
  169.             IF B$ = "[" THEN                    ' ANSI sequence
  170.                CALL GetChar(B$): GOSUB 740
  171.                IF B$ = "C" THEN
  172.                   KeyPressed = ColRightKey
  173.                ELSEIF B$ = "D" THEN
  174.                   KeyPressed = ColLeftKey
  175.                ELSEIF B$ = "A" THEN
  176.                   KeyPressed = LineUpKey
  177.                ELSEIF B$ = "B" THEN
  178.                   KeyPressed = LineDownKey
  179.                END IF
  180.             END IF
  181.          END IF
  182.  
  183.          Index = CurrentRow + TopLine - 3
  184.  
  185.          IF BlockDelActive OR Index <= MsgLockLines OR Index > ZMaxMsgLines THEN
  186. 530         SELECT CASE KeyPressed
  187.                CASE CarrRet
  188.                   IF BlockDelActive THEN
  189.                      BlockDelActive = ZFalse
  190.                      BlockLine2 = Index
  191.                      IF BlockLine2 < BlockLine1 THEN
  192.                         SWAP BlockLine1, BlockLine2
  193.                      END IF
  194.                      IF BlockLine1 <= MsgLockLines THEN
  195.                         BlockLine1 = MsgLockLines + 1
  196.                      END IF
  197.                      IF BlockLine2 > ZMaxMsgLines THEN
  198.                         BlockLine2 = ZMaxMsgLines
  199.                      END IF
  200.                      K = 0
  201.                      FOR I = BlockLine2 + 1 TO 99
  202.                         ZOutTxt$(BlockLine1 + K) = ZOutTxt$(I)
  203.                         K = K + 1
  204.                      NEXT I
  205.                      WHILE BlockLine1 + K <= 99
  206.                         ZOutTxt$(BlockLine1 + K) = BlankLine$
  207.                         K = K + 1
  208.                      WEND
  209.                      CALL UpdateScreen
  210.                      CALL UpdateStatusLine(2)
  211.                      CALL MoveCursor(BlockRow, BlockCol)
  212.                   END IF
  213.                   KeyPressed = 255
  214.  
  215. 540            CASE ESCKey
  216.                   IF BlockDelActive THEN
  217.                      BlockDelActive = ZFalse
  218.                      CALL UpdateStatusLine(2)
  219.                      CALL MoveCursor(BlockRow, BlockCol)
  220.                      KeyPressed = 255
  221.                   END IF
  222.  
  223.                CASE LineUpKey, LineDownKey, PageDownKey, PageUpKey
  224.                   '*
  225.                   '* Up and Down get passed on
  226.                   '*
  227.                CASE ELSE
  228.                   '*
  229.                   '* Ignore the key
  230.                   '*
  231.                   KeyPressed = 255
  232.  
  233.             END SELECT
  234.          END IF
  235.  
  236. 560      SELECT CASE KeyPressed
  237.             CASE ESCKey, EndSessionKey
  238.                '*
  239.                '* User wants to see main menu
  240.                '*
  241.                CALL DisplayMainMenu
  242.                CALL MoveCursor(RowSave, ColSave)
  243.                CALL GetChar(B$): GOSUB 740
  244.                CALL AllCaps(B$)
  245.                IF B$ = "D" THEN
  246.                   BlockDelActive = ZTrue
  247.                   BlockLine1 = RowSave + TopLine - 3
  248.                   BlockCol = ColSave
  249.                   BlockRow = RowSave
  250.                   CALL EraseToEOL(1, 1)
  251.                   ' v2.44a
  252.                   CALL PutScreen("Delete Block: Press ENTER on Last Line to Delete, or ESC Twice to Quit", DefaultColor, DefaultBold)
  253.                   BlockLine2 = 0
  254.                ELSE
  255.                   CALL MenuCommand(B$): GOSUB 740
  256.                END IF
  257.                CALL MoveCursor(RowSave, ColSave)
  258.  
  259. 570         CASE LineUpKey
  260.                '*
  261.                '* Move the current cursor position up one line
  262.                '*
  263.                IF CurrentRow > 3 THEN
  264.                   CALL MoveCursor(CurrentRow - 1, CurrentCol)
  265.                ELSE
  266.                   IF TopLine <> 1 THEN
  267.                      TopLine = TopLine - 11
  268.                      CALL MoveCursor(CurrentRow + 10, CurrentCol)
  269.                      CALL UpdateScreen
  270.                   END IF
  271.                END IF
  272.  
  273. 580         CASE LineDownKey
  274.                '*
  275.                '* Move the current cursor position down one line
  276.                '*
  277.                IF CurrentRow < 24 THEN
  278.                   CALL MoveCursor(CurrentRow + 1, CurrentCol)
  279.                ELSE
  280.                   IF NOT TopLine = 78 THEN
  281.                      TopLine = TopLine + 11
  282.                      CALL MoveCursor(CurrentRow - 10, CurrentCol)
  283.                      CALL UpdateScreen
  284.                   END IF
  285.                END IF
  286.  
  287. 590         CASE ColLeftKey
  288.                '*
  289.                '* Move the current cursor left one column
  290.                '*
  291.                IF CurrentCol > 1 THEN
  292.                   CALL MoveCursor(CurrentRow, CurrentCol - 1)
  293.                END IF
  294.  
  295. 600         CASE ColRightKey
  296.                '*
  297.                '* Move the current cursor right one column
  298.                '*
  299.                IF CurrentCol < 79 THEN
  300.                   CALL MoveCursor(CurrentRow, CurrentCol + 1)
  301.                END IF
  302.  
  303. 610         CASE WordRightKey, WordLeftKey
  304.                '*
  305.                '* Move the current cursor one word
  306.                '*
  307.                I = KeyPressed - WordLeftKey
  308.                NewCol = CurrentCol
  309.                CALL FindWord(ZOutTxt$(Index), I, NewCol)
  310.                IF NewCol > 79 THEN
  311.                   NewCol = 79
  312.                END IF
  313.                CALL MoveCursor(CurrentRow, NewCol)
  314.  
  315. 620         CASE DeleteWordRightKey
  316.                '*
  317.                '* Delete the current word
  318.                '*
  319.                I = CurrentCol
  320.                L = LEN(ZOutTxt$(Index))
  321.                CALL FindWord(ZOutTxt$(Index), 1, I)
  322.                IF I > CurrentCol THEN
  323.                   YY$ = MID$(ZOutTxt$(Index), I)
  324.                   MID$(ZOutTxt$(Index), CurrentCol) = YY$
  325.                   ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), L - (I - CurrentCol))
  326.                   CALL PutScreen(YY$, YellowFore, ZTrue)
  327.                   CALL EraseToEOL(RowSave, CurrentCol)
  328.                   CALL MoveCursor(RowSave, ColSave)
  329.                END IF
  330.  
  331. 630         CASE HomeKey
  332.                '*
  333.                '* Move cursor to the start of the line
  334.                '*
  335.                CALL MoveCursor(CurrentRow, 1)
  336.  
  337. 640         CASE EndKey
  338.                '*
  339.                '* Move cursor to the end of the line
  340.                '*
  341.                NewCol = LEN(ZOutTxt$(Index)) + 1
  342.                IF NewCol > 79 THEN
  343.                   NewCol = 79
  344.                END IF
  345.                CALL MoveCursor(CurrentRow, NewCol)
  346.  
  347. 650         CASE PageDownKey
  348.                '*
  349.                '* Move the display one page down
  350.                '*
  351.                TopLine = TopLine + 22
  352.                IF TopLine > 78 THEN
  353.                   TopLine = 78
  354.                END IF
  355.                CALL UpdateScreen
  356.  
  357. 660         CASE PageUpKey
  358.                '*
  359.                '* Move the display one page up
  360.                '*
  361.                TopLine = TopLine - 22
  362.                IF TopLine < 1 THEN
  363.                   TopLine = 1
  364.                END IF
  365.                CALL UpdateScreen
  366.  
  367. 670         CASE LineDeleteKey
  368.                '*
  369.                '* Delete the current line in the file
  370.                '*
  371.                CALL DeleteCurrentLine(Index)
  372.                CALL MoveCursor(RowSave, ColSave)
  373.  
  374. 680         CASE CharDeleteKey
  375.                '*
  376.                '* Delete the current character
  377.                '*
  378.                IF CurrentCol <= LEN(ZOutTxt$(Index)) THEN
  379.                   CALL MoveCursor(CurrentRow, CurrentCol + 1)
  380.                   CALL BackspChar
  381.                END IF
  382.  
  383. 690         CASE BackspKey, OtherBackspKey
  384.                '*
  385.                '* Back up one character and destroy it
  386.                '*
  387.                CALL BackspChar
  388.  
  389. 700         CASE CarrRet
  390.                '*
  391.                '* Move to the next line, left column
  392.                '*
  393.                IF NOT Index >= ZMaxMsgLines THEN
  394.                   CALL CarrRetKey
  395.                END IF
  396.  
  397. 710         CASE HelpKey, ReformTextKey, ReflowTextKey, ToggleINSKey, RepaintKey
  398.                '*
  399.                '* Execute a main menu command
  400.                '*
  401.                '*          1234567890123456789012
  402.                YY$ = MID$(" J           HRP     I", KeyPressed, 1)
  403.                CALL MenuCommand(YY$): GOSUB 740
  404.                CALL MoveCursor(RowSave, ColSave)
  405.  
  406.             CASE IS > 127, IS < 32
  407.                '*
  408.                '* Ignore characters above 127 or below 32
  409.                '*
  410. 720         CASE ELSE
  411.                '*
  412.                '* Input was a normal character
  413.                '*
  414.                CALL NormalChar(B$)
  415.  
  416.          END SELECT
  417.       WEND
  418.  
  419. 730   REDIM ZWorkAra$(13)
  420.       ZHiLiteOff = HiLiteSave
  421.       ZUseTput = UseTputSave
  422.       S$ = MsgSubj$
  423.       CALL AllCaps(S$)
  424.       EXIT SUB
  425.  
  426.       '*
  427.       '* Test ZSubParm and Exit ANSIED if the carrier dropped
  428.       '*
  429. 740   IF ZSubParm <> 0 THEN
  430.          GOTO 730
  431.       END IF
  432.       RETURN
  433.  
  434.       END SUB         ' Sub AnsiEd
  435.  
  436. '*  BackspChar()
  437. '*----------------------------------------------------------------------------
  438. '*  This routine handles the user entering the backspace key
  439. '*
  440. '*
  441.       SUB BackspChar STATIC
  442. 1200  CALL SaveCursor(RowSave, ColSave)
  443.       Index = TopLine + CurrentRow - 3
  444.       IF Index = MsgLockLines + 1 AND CurrentCol = 1 THEN
  445.          EXIT SUB
  446.       END IF
  447.       AtEndOfLine = CurrentCol > LEN(ZOutTxt$(Index))
  448. 1210  IF CurrentCol > 1 THEN
  449.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 2) + MID$(ZOutTxt$(Index), CurrentCol)
  450.          CALL EraseToEOL(CurrentRow, CurrentCol - 1)
  451.          IF NOT AtEndOfLine THEN
  452.             YY$ = MID$(ZOutTxt$(Index), ColSave - 1)
  453.             CALL MoveCursor(RowSave, ColSave - 1)
  454.             CALL PutScreen(YY$, YellowFore, ZTrue)
  455.          END IF
  456.          CALL MoveCursor(RowSave, ColSave - 1)
  457.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  458.       ELSEIF LEN(ZOutTxt$(Index - 1)) >= ZRightMargin THEN
  459.          '*
  460.          '* Do nothing
  461.          '*
  462. 1220  ELSE
  463.          NewCol = LEN(ZOutTxt$(Index - 1)) + 1
  464.          YY$ = ZOutTxt$(Index)
  465.          CALL UnString(YY$, SoftSpace$)
  466.          ZOutTxt$(Index - 1) = ZOutTxt$(Index - 1) + YY$
  467.                                    ' v2.44a
  468.          IF LEN(ZOutTxt$(Index - 1)) <= ZRightMargin THEN
  469.             CALL DeleteCurrentLine(Index)
  470. 1230     ELSE
  471.             CALL FindWrap(LEFT$(ZOutTxt$(Index - 1), ZRightMargin + 1), I)
  472.             IF I <= 1 THEN
  473.                I = ZRightMargin
  474.             END IF
  475.             ZOutTxt$(Index) = MID$(ZOutTxt$(Index - 1), I + 1)
  476.             ZOutTxt$(Index - 1) = LEFT$(ZOutTxt$(Index - 1), I)
  477.          END IF
  478.          IF RowSave > 3 THEN
  479.             CALL MoveCursor(RowSave - 1, NewCol)
  480.             CALL UpdateScreen
  481.          ELSE
  482.             CALL MoveCursor(RowSave, NewCol)
  483.             CALL UnGetChar(LineUpKey)
  484.          END IF
  485.       END IF
  486.       END SUB
  487.  
  488. '*  CarrRetKey()
  489. '*----------------------------------------------------------------------------
  490. '*  This routine handles carriage returns entered in the file
  491. '*
  492. '*
  493.       SUB CarrRetKey STATIC
  494. 1300  Index = CurrentRow + TopLine - 3
  495.       IF Index >= 99 THEN
  496.          EXIT SUB
  497.       END IF
  498.       IF InsertMode THEN         ' Insert a new line
  499.          FOR I = 98 TO Index + 1 STEP -1
  500.             ZOutTxt$(I + 1) = ZOutTxt$(I)
  501.          NEXT I
  502.          IF LEN(ZOutTxt$(Index)) >= CurrentCol THEN
  503.             ZOutTxt$(Index + 1) = MID$(ZOutTxt$(Index), CurrentCol)
  504.             ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1)
  505.          ELSE
  506.             ZOutTxt$(Index + 1) = BlankLine$
  507.          END IF
  508.          CALL UpdateScreen
  509.       END IF
  510.       IF CurrentRow < 24 THEN
  511.          CALL MoveCursor(CurrentRow + 1, 1)
  512.       ELSE
  513.          CALL MoveCursor(CurrentRow, 1)
  514.          CALL UnGetChar(LineDownKey)
  515.       END IF
  516.       END SUB
  517.  
  518. '*  ChangeSubject()
  519. '*----------------------------------------------------------------------------
  520. '*  Routine to allow user to change the message subject
  521. '*
  522. '*
  523.       SUB ChangeSubject STATIC
  524.       CALL GetString("Change Subject From '" + MsgSubj$ + "' To? ", NewSubj$)
  525.       IF NewSubj$ <> "" THEN
  526.          MsgSubj$ = LEFT$(NewSubj$, 25)
  527.          CALL NameCaps(MsgSubj$)
  528.       END IF
  529.       END SUB
  530.  
  531. '*  ClearScreen()
  532. '*----------------------------------------------------------------------------
  533. '*  This routine clears the screen and moves the cursor to row 2, col 1
  534. '*
  535. '*
  536.       SUB ClearScreen STATIC
  537. 1500  FOR I = 1 TO 23
  538.          ZWorkAra$(I) = BlankLine$
  539.       NEXT I
  540.       CALL QuickTput("", 0)
  541.       ZSubParm = 2
  542.       CALL Line25
  543.       ZSubParm = 0
  544.       CALL QuickTput("H" + ZEmphasizeOff$, 0)
  545.       CurrentCol = 1
  546.       CurrentRow = 3
  547.       IsBold = DefaultBold
  548.       OldColour = DefaultColor
  549.       END SUB
  550.  
  551. '*  DeleteCurrentLine()
  552. '*----------------------------------------------------------------------------
  553. '*  This routine deletes the current line on the screen and in the array
  554. '*  ZOutTxt$, and moves the next lower line up one  It then repaints the
  555. '*  affected portion of the screen (from the deleted line down)
  556. '*
  557. '*
  558.       SUB DeleteCurrentLine (Index%) STATIC
  559. 1600  FOR I = Index% TO 98
  560.          ZOutTxt$(I) = ZOutTxt$(I + 1)
  561.       NEXT I
  562.       ZOutTxt$(99) = BlankLine$
  563.       CALL UpdateScreen
  564.       END SUB
  565.  
  566. '*  DisplayMainMenu()
  567. '*----------------------------------------------------------------------------
  568. '*  This routine displays the main menu on the top line
  569. '*
  570. '*
  571.       SUB DisplayMainMenu STATIC
  572. 1700  CALL MoveCursor(1, 1)
  573.       YY$ = "A)bort H)elp D)elete I)ns/ovw J)ustify "
  574.       IF ZLocalUser OR ZSysop THEN
  575.          YY$ = YY$ + "O)import R)eflow P)aint S)ave U)subject "
  576.       ELSE
  577.          YY$ = YY$ + "R)eflow P)aint S)ave U)subject          "
  578.       END IF
  579.       CALL ColorPrompt(YY$)
  580.       CALL PutScreen(YY$, DefaultColor, DefaultBold)
  581.       END SUB
  582.  
  583. '*  DoneWithMsg()
  584. '*----------------------------------------------------------------------------
  585. '*  This routine is called to save or abort the message
  586. '*
  587. '*
  588.       SUB DoneWithMsg (YY$) STATIC
  589. 1810  SELECT CASE YY$
  590.          CASE "S"        ' Save Message
  591.             '*
  592.             '* Remove trailing blank lines from the message
  593.             '*
  594.             CALL FindEndOfMsg(EndOfMsg)
  595.             FOR I = 1 TO EndOfMsg
  596.                J = INSTR(ZOutTxt$(I), SoftSpace$)
  597.                WHILE J <> 0
  598.                   MID$(ZOutTxt$(I), J, 1) = " "
  599.                   J = INSTR(ZOutTxt$(I), SoftSpace$)
  600.                WEND
  601.                CALL TrimTrail(ZOutTxt$(I), " ")
  602.             NEXT I
  603.             CALL FindEndOfMsg(ZLinesInMsg)
  604.             CALL ClearScreen
  605.             ZSubParm = 1
  606.  
  607. 1820     CASE "A"
  608.             CALL EraseToEOL(1, 1)
  609.             YY$ = "Abort: Are You Sure (Y)es,[N]o)? "
  610.             CALL ColorPrompt(YY$)
  611.             CALL PutScreen(YY$, DefaultColor, DefaultBold)
  612.             CALL GetChar(B$)
  613.             IF ZSubParm <> 0 THEN
  614.                B$ = "Y"
  615.             END IF
  616.             CALL AllCaps(B$)
  617.             IF B$ = "Y" THEN
  618.                CALL ClearScreen
  619.                ZSubParm = 2
  620.             END IF
  621.  
  622.          CASE ELSE
  623.  
  624.       END SELECT
  625.       END SUB
  626.  
  627. '*  EraseToEOL()
  628. '*----------------------------------------------------------------------------
  629. '*  This routine clears from a position to to the end of that line
  630. '*
  631. '*
  632.       SUB EraseToEOL (LineNumber, ColNumber) STATIC
  633. 1900  CALL MoveCursor(LineNumber, ColNumber)
  634.       CALL QuickTput("", 0)
  635.       END SUB
  636.  
  637. '*  FindEndOfMsg()
  638. '*----------------------------------------------------------------------------
  639. '*  Finds the last active line in the message
  640. '*
  641. '*
  642.       SUB FindEndOfMsg (EndOfMsg) STATIC
  643.       EndOfMsg = 1
  644.       FOR I = ZMaxMsgLines TO 1 STEP -1
  645.          IF ZOutTxt$(I) <> BlankLine$ OR I <= MsgLockLines THEN
  646.             EndOfMsg = I
  647.             EXIT FOR
  648.          END IF
  649.       NEXT I
  650.       END SUB
  651.  
  652. '*  FindWrap()
  653. '*----------------------------------------------------------------------------
  654. '*  This routine finds a place in the string yy$ that could be used as a
  655. '*  place to wrap the line WhereToWrap should be the last position that
  656. '*  remains in the line, ie
  657. '*    set   currentline$ = left$(yy$,wheretowrap)
  658. '*          nextline$    = mid$ (yy$,wheretowrap+1)
  659. '*
  660. '*
  661.       SUB FindWrap (YY$, WhereToWrap) STATIC
  662. 2100  WhereToWrap = LEN(YY$) + 1
  663.       CALL FindWord(YY$, 0, WhereToWrap)
  664.       WhereToWrap = WhereToWrap - 1
  665.       END SUB
  666.  
  667. '*  GetChar()
  668. '*----------------------------------------------------------------------------
  669. '*  This routine reads a character from the user into YY$
  670. '*
  671. '*
  672.       SUB GetChar (YY$) STATIC
  673. 2200  ZAutoLogoff! = TIMER + ZWaitBeforeDisconnect
  674.       CALL Carrier
  675.       YY$ = ""
  676.       WHILE ZSubParm <> -1 AND ZSubParm <> -2 AND YY$ = ""
  677.          ZSubParm = 0
  678.          IF LEN(ZCommportStack$) > 0 THEN
  679.             YY$ = LEFT$(ZCommportStack$, 1)
  680.             ZCommportStack$ = MID$(ZCommportStack$, 2)
  681.          ELSE
  682.             IF ZLocalUser THEN
  683.                YY$ = INKEY$
  684.                IF LEN(YY$) = 2 THEN
  685.                   KeyPressed = ASC(RIGHT$(YY$, 1))
  686.                   YY$ = ""
  687.                   SELECT CASE KeyPressed
  688.                      CASE 82                  ' Insert
  689.                         KeyPressed = ToggleINSKey
  690.                      CASE 83                  ' Delete
  691.                         KeyPressed = CharDeleteKey
  692.                      CASE 71                  ' Home
  693.                         KeyPressed = HomeKey
  694.                      CASE 73                  ' PgUp
  695.                         KeyPressed = PageUpKey
  696.                      CASE 72                  ' Up Arrow
  697.                         KeyPressed = LineUpKey
  698.                      CASE 80                  ' Down Arrow
  699.                         KeyPressed = LineDownKey
  700.                      CASE 81                  ' PgDn
  701.                         KeyPressed = PageDownKey
  702.                      CASE 75                  ' Left Arrow
  703.                         KeyPressed = ColLeftKey
  704.                      CASE 77                  ' Right Arrow
  705.                         KeyPressed = ColRightKey
  706.                      CASE 115                 ' Ctrl-Left Arrow
  707.                         KeyPressed = WordLeftKey
  708.                      CASE 116                 ' Ctrl-Right Arrow
  709.                         KeyPressed = WordRightKey
  710.                      CASE 79                  ' End
  711.                         KeyPressed = EndKey
  712.                      CASE ELSE
  713.                         KeyPressed = 0
  714.                   END SELECT
  715.                   IF KeyPressed <> 0 THEN
  716.                      YY$ = CHR$(KeyPressed)
  717.                   END IF
  718.                END IF
  719.             ELSE
  720.                CALL FindFKey
  721.                IF ZSubParm >= 0 THEN
  722.                   YY$ = ZKeyPressed$
  723.                   IF YY$ = "" THEN
  724.                      CALL EofComm(Char%)
  725.                      IF Char% = -1 THEN
  726.                         CALL CheckTime(ZAutoLogoff!, Remain!, 1)
  727.                         IF Remain! < 0 THEN
  728.                            CALL UpdtCalr("Sleep disconnect", 1)
  729.                            ZSubParm = -2
  730.                            ZNo = ZTrue
  731.                            ZSleepDisconnect = ZTrue
  732.                         END IF
  733.                      ELSE
  734.                         CALL Carrier
  735.                         IF ZSubParm <> -1 THEN
  736.                            ZSubParm = 0
  737.                            CALL GetCom(YY$)
  738.                         END IF
  739.                      END IF
  740.                   END IF
  741.                END IF
  742.             END IF
  743.          END IF
  744.       WEND
  745.       END SUB
  746.  
  747. '*  GetString()
  748. '*----------------------------------------------------------------------------
  749. '*  Gets a string from the user
  750. '*
  751. '*
  752.       SUB GetString (Prompt$, YY$) STATIC
  753.       YY$ = ""
  754.       CALL EraseToEOL(1, 1)
  755.       CALL PutScreen(Prompt$, DefaultColor, DefaultBold)
  756.       NewCol = CurrentCol
  757.       InitCol = NewCol
  758.       DO
  759.          CALL MoveCursor(CurrentRow, NewCol)
  760.          CALL GetChar(B$)
  761.          IF ZSubParm <> 0 THEN
  762.             B$ = CHR$(ESCKey)
  763.          END IF
  764.          KeyPressed = ASC(B$)
  765.          SELECT CASE KeyPressed
  766.             CASE BackspKey, OtherBackspKey
  767.                IF NewCol <> InitCol THEN
  768.                   CALL MoveCursor(CurrentRow, NewCol - 1)
  769.                   CALL PutScreen(" ", DefaultColor, DefaultBold)
  770.                   NewCol = NewCol - 1
  771.                   YY$ = LEFT$(YY$, LEN(YY$) - 1)
  772.                END IF
  773.             CASE CarrRet
  774.                EXIT DO
  775.             CASE ESCKey
  776.                YY$ = ""
  777.                EXIT DO
  778.             CASE ELSE
  779.                YY$ = YY$ + B$
  780.                CALL PutScreen(B$, DefaultColor, DefaultBold)
  781.                NewCol = NewCol + 1
  782.          END SELECT
  783.       LOOP WHILE 1
  784.       END SUB
  785.  
  786. '*  HelpMe()
  787. '*----------------------------------------------------------------------------
  788. '*  This routine provides on-line help for the user
  789. '*
  790. '*
  791.       SUB HelpMe STATIC
  792. 2300  CALL SaveCursor(RowSave, ColSave)
  793.       CALL ClearScreen
  794.       CALL BufFile(ZHelpPath$ + "ANSIED" + ZHelpExtension$, X)
  795.       CALL ClearScreen
  796.       CALL UpdateScreen
  797.       CALL MoveCursor(RowSave, ColSave)
  798.       END SUB
  799.  
  800. '*  ImportFile()
  801. '*----------------------------------------------------------------------------
  802. '*  Imports an ASCII text file in the message
  803. '*
  804. '*
  805.       SUB ImportFile STATIC
  806.       IF ZLocalUser OR ZSysop THEN
  807.          CALL GetString("Import What File? ", FileName$)
  808.          IF FileName$ <> "" THEN
  809.             CALL FindIt(FileName$)
  810.             IF ZOK THEN
  811.                ZUserIn$(1) = FileName$
  812.                ZAnsIndex = 0
  813.                ZLastIndex = 1
  814.                CALL FindEndOfMsg(EndOfMsg)
  815.                CALL MsgImport(ZMaxMsgLines, ZRightMargin, EndOfMsg, ZOutTxt$())
  816.                CALL UpdateScreen
  817.             END IF
  818.          END IF
  819.       END IF
  820.       END SUB
  821.  
  822. '*  LastParaLine()
  823. '*----------------------------------------------------------------------------
  824. '*  This routine returns ZTrue if ZOutTxt$(I) is the last line
  825. '*  in a paragraph
  826. '*
  827. '*
  828.       SUB LastParaLine (I, LastLine, Result) STATIC
  829. 2400  Result = ZFalse
  830.       IF I = LastLine OR I >= ZMaxMsgLines THEN
  831.          Result = ZTrue
  832.       ELSE
  833.          YY$ = ZOutTxt$(I)
  834.          J = INSTR(YY$, ">")
  835.          IF J = 0 THEN
  836.             J = 6
  837.          END IF
  838.          IF J < 5 THEN
  839.             Result = ZTrue
  840.          ELSEIF YY$ = BlankLine$ THEN
  841.             Result = ZTrue
  842.          ELSE
  843.             IF ZOutTxt$(I + 1) = BlankLine$ THEN
  844.                Result = ZTrue
  845.             ELSEIF LEFT$(ZOutTxt$(I + 1), 1) = " " THEN
  846.                Result = ZTrue
  847.             ELSE
  848.                K = INSTR(ZOutTxt$(I + 1), ">")
  849.                IF K <> 0 AND K < 5 THEN
  850.                   Result = ZTrue
  851.                END IF
  852.             END IF
  853.          END IF
  854.       END IF
  855.       END SUB
  856.  
  857. '*  MenuCommand()
  858. '*----------------------------------------------------------------------------
  859. '* This routine executes the passed main menu command
  860. '*
  861. '*
  862.       SUB MenuCommand (YY$) STATIC
  863. 2450  ZSubParm = 0              ' v2.44a
  864.       SELECT CASE YY$
  865.          CASE "H"
  866.             CALL HelpMe
  867.          CASE "S", "A"
  868.             CALL DoneWithMsg(YY$)
  869.          CASE "P"
  870.             CALL ClearScreen
  871.             CALL UpdateScreen
  872.          CASE "I"
  873.             InsertMode = NOT InsertMode
  874.          CASE "R"
  875.             CALL ReformText(ZFalse)
  876.          CASE "J"
  877.             CALL ReformText(ZTrue)
  878.          CASE "O"
  879.             CALL ImportFile
  880.          CASE "U"
  881.             CALL ChangeSubject
  882.          CASE ELSE
  883.       END SELECT
  884.       IF ZSubParm = 0 THEN
  885.          CALL EraseToEOL(1, 1)
  886.          CALL UpdateStatusLine(1)
  887.       END IF
  888.       END SUB
  889.  
  890. '*  MoveCursor()
  891. '*----------------------------------------------------------------------------
  892. '*  This routine moves the cursor to the position spec'd by newcol and
  893. '*  newrow and tries to do it with the minimum number of Ansi characters
  894. '*
  895. '*
  896.       SUB MoveCursor (NewRow, NewCol) STATIC
  897. 2500  YY$ = "        "
  898.       CALL MoveCurStr(CurrentRow, CurrentCol, NewRow, NewCol, YY$, YLen)
  899.       IF YLen <> 0 THEN
  900.          YY$ = LEFT$(YY$, YLen)
  901.          CALL QuickTput(YY$, 0)
  902.       END IF
  903.       ZSubParm = 0
  904.       END SUB
  905.  
  906. '*  NormalChar()
  907. '*----------------------------------------------------------------------------
  908. '*  This routine handles 'normal' characters entered into the message
  909. '*
  910. '*
  911.       SUB NormalChar (YY$) STATIC
  912.  
  913. 2600  CALL SaveCursor(RowSave, ColSave)
  914.       Index = CurrentRow + TopLine - 3
  915.       CurrentLineBlank = (ZOutTxt$(Index) = BlankLine$)
  916.       LML = LEN(ZOutTxt$(Index))
  917.  
  918.       IF CurrentCol > 79 THEN
  919.          EXIT SUB
  920.       END IF
  921.  
  922.       AtEndOfLine = ZFalse
  923.  
  924.       IF CurrentCol > LML THEN
  925.          ZOutTxt$(Index) = ZOutTxt$(Index) + SPACE$(CurrentCol - LML)
  926.          ZWorkAra$(CurrentRow) = ZWorkAra$(CurrentRow) + SPACE$(CurrentCol - LML)
  927.          LML = LEN(ZOutTxt$(Index))
  928.          AtEndOfLine = ZTrue
  929.       END IF
  930.  
  931. 2610  IF (CurrentCol <= ZRightMargin AND AtEndOfLine) OR (CurrentCol <= ZRightMargin AND NOT InsertMode) THEN
  932.          '*
  933.          '* Single character changed
  934.          '*
  935.          MID$(ZOutTxt$(Index), CurrentCol, 1) = YY$
  936.          MID$(ZWorkAra$(CurrentRow), CurrentCol, 1) = YY$
  937.          CALL PutScreen(YY$, YellowFore, ZTrue)
  938.                                                                                     ' v2.44a
  939. 2620  ELSEIF (NOT AtEndOfLine AND InsertMode AND CurrentCol <= ZRightMargin AND LML < ZRightMargin) THEN
  940.          '*
  941.          '* Have to rewrite the screen from the current pos forward
  942.          '*
  943.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1) + YY$ + MID$(ZOutTxt$(Index), CurrentCol)
  944.  
  945.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  946.  
  947.          CALL EraseToEOL(CurrentRow, CurrentCol)
  948.          ZZ$ = MID$(ZWorkAra$(CurrentRow), CurrentCol)
  949.          CALL PutScreen(ZZ$, YellowFore, ZTrue)
  950.          CALL MoveCursor(RowSave, ColSave + 1)
  951.  
  952. 2630  ELSE
  953.          '*
  954.          '* Wrap the end of the line
  955.          '*
  956.          IF NOT AtEndOfLine THEN
  957.             ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1) + YY$ + MID$(ZOutTxt$(Index), CurrentCol)
  958.             LML = LML + 1
  959.          ELSE
  960.             MID$(ZOutTxt$(Index), CurrentCol, 1) = YY$
  961.          END IF
  962.  
  963.          CALL FindWrap(ZOutTxt$(Index), I)
  964.          IF I <= 1 THEN
  965.             I = ZRightMargin
  966.          END IF
  967.  
  968.          ZZ$ = MID$(ZOutTxt$(Index), (I + 1))
  969.          CALL TrimTrail(ZZ$, SoftSpace$)
  970.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), I)
  971.          '*
  972.          '* Add to the beginning of a new line
  973.          '*
  974.          IF Index <= 98 THEN
  975.             Index = Index + 1
  976.          END IF
  977.  
  978.          Z = INSTR(ZOutTxt$(Index), ">")                                                  ' v2.44a
  979.          IF ZOutTxt$(Index) <> BlankLine$ AND (Z <= 0 OR Z > 6) AND LEN(ZOutTxt$(Index)) + LEN(ZZ$) < ZRightMargin THEN
  980.             ZOutTxt$(Index) = ZZ$ + ZOutTxt$(Index)
  981.          ELSE
  982.             FOR J = 98 TO Index STEP -1
  983.                ZOutTxt$(J + 1) = ZOutTxt$(J)
  984.             NEXT J
  985.             ZOutTxt$(Index) = ZZ$
  986.          END IF
  987.  
  988.          CALL EraseToEOL(CurrentRow, I + 1)        ' do the "easy" line
  989.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  990.  
  991.          CALL UpdateScreen
  992.          IF (ColSave > I) THEN
  993.             NewCol = ColSave - I + 1
  994.             IF RowSave <> 24 THEN
  995.                CALL MoveCursor(RowSave + 1, NewCol)
  996.             ELSE
  997.                CALL MoveCursor(RowSave, NewCol)
  998.                CALL UnGetChar(LineDownKey)
  999.             END IF
  1000.          ELSE
  1001.             CALL MoveCursor(RowSave, ColSave + 1)
  1002.          END IF
  1003.       END IF
  1004.  
  1005.       END SUB
  1006.  
  1007. '*  PutScreen()
  1008. '*----------------------------------------------------------------------------
  1009. '* This routine writes YY$ to the user in the color and
  1010. '* intensity specified
  1011. '*
  1012. '*
  1013.       SUB PutScreen (YY$, Colour, Bold) STATIC
  1014. 2800  ZZ$ = ""
  1015.       IF Colour <> 99 THEN
  1016.          IF (Colour <> OldColour) OR (Bold <> IsBold) THEN
  1017.             ZZ$ = ""
  1018.             IF Bold <> IsBold THEN
  1019.                IF Bold THEN
  1020.                   ZZ$ = ZZ$ + "1;"
  1021.                ELSE
  1022.                   ZZ$ = ZZ$ + "0;"
  1023.                END IF
  1024.             END IF
  1025.             ZZ$ = ZZ$ + MID$(STR$(Colour), 2) + "m"
  1026.          END IF
  1027.       ELSE
  1028.          ZZ$ = ZEmphasizeOff$
  1029.       END IF
  1030.       ZOutTxt$ = ZZ$ + YY$
  1031.       IF ZLocalUser THEN
  1032.          CALL QuickTput(ZOutTxt$, 0)
  1033.       ELSE
  1034.          ZSubParm = 4
  1035.          CALL Tput
  1036.       END IF
  1037.       ZSubParm = 0
  1038.       IF INSTR(YY$, "") = 0 THEN
  1039.          CurrentCol = CurrentCol + LEN(YY$)
  1040.          IF CurrentCol > 80 THEN
  1041.             CurrentCol = 0
  1042.             CurrentRow = 0
  1043.          END IF
  1044.       ELSE
  1045.          CurrentRow = 0
  1046.          CurrentCol = 0
  1047.       END IF
  1048.       OldColour = Colour
  1049.       IsBold = Bold
  1050.       END SUB
  1051.  
  1052. '*  ReformText()
  1053. '*----------------------------------------------------------------------------
  1054. '*  This routine reflows the text to the current margins.  Optionally,
  1055. '*  it right justifies all lines by adding "soft spaces"
  1056. '*
  1057. '*
  1058.       SUB ReformText (Justify%) STATIC
  1059.  
  1060. 2900  DIM Places(80)
  1061.  
  1062.       CALL EraseToEOL(1, 1)
  1063.       CALL PutScreen("Reformatting... Please Wait.", WhiteFore, ZTrue)
  1064.  
  1065.       CALL FindEndOfMsg(EndOfMsg)
  1066.  
  1067.       I = MsgLockLines + 1   ' Read index
  1068.       J = MsgLockLines + 1   ' Write index
  1069.  
  1070.       '*
  1071.       '* Reflow the text to the maximum on a line
  1072.       '*
  1073.       DO WHILE I <= EndOfMsg
  1074.          '*
  1075.          '* Loop until we get a long line or an end of paragraph
  1076.          '*
  1077.          ZOutTxt$ = ""
  1078.          DO WHILE 1
  1079.             YY$ = ZOutTxt$(I)
  1080.             CALL UnString(YY$, SoftSpace$)
  1081.             IF ZOutTxt$ <> "" AND RIGHT$(ZOutTxt$, 1) <> " " THEN
  1082.                ZOutTxt$ = ZOutTxt$ + " "
  1083.             END IF
  1084.             ZOutTxt$ = ZOutTxt$ + YY$
  1085.             CALL LastParaLine(I, EndOfMsg, EndOfPara)
  1086.             I = I + 1
  1087.             IF LEN(ZOutTxt$) > ZRightMargin THEN
  1088.                '*
  1089.                '* Wrap the long line
  1090.                '*
  1091.                CALL FindWrap(LEFT$(ZOutTxt$, ZRightMargin + 1), K)
  1092.                IF K <= 1 THEN
  1093.                   K = ZRightMargin
  1094.                END IF
  1095.                ZOutTxt$(J) = LEFT$(ZOutTxt$, K)
  1096.                IF EndOfPara THEN
  1097.                   '*
  1098.                   '* Go to the next paragraph
  1099.                   '*
  1100.                   J = J + 1
  1101.                   ZOutTxt$(J) = MID$(ZOutTxt$, K + 1)
  1102.                ELSE
  1103.                   '*
  1104.                   '* Keep the remaining part of the line and process
  1105.                   '* it on the next pass
  1106.                   '*
  1107.                   I = I - 1
  1108.                   ZOutTxt$(I) = MID$(ZOutTxt$, K + 1)
  1109.                END IF
  1110.                J = J + 1
  1111.                EXIT DO
  1112.             ELSEIF EndOfPara THEN
  1113.                ZOutTxt$(J) = ZOutTxt$
  1114.                J = J + 1
  1115.                EXIT DO
  1116.             END IF
  1117.          LOOP
  1118.       LOOP
  1119.  
  1120.       FOR I = J TO 99
  1121.          ZOutTxt$(I) = BlankLine$
  1122.       NEXT
  1123.  
  1124.       EndOfMsg = J - 1
  1125.  
  1126.       '*
  1127.       '* Space out the text on each line
  1128.       '*
  1129.       IF Justify% THEN
  1130.          FOR I = MsgLockLines + 1 TO EndOfMsg
  1131.             CALL LastParaLine(I, EndOfMsg, EndOfPara)
  1132.             IF NOT EndOfPara THEN
  1133.                '*
  1134.                '* Space out the line
  1135.                '*
  1136.                ZOutTxt$ = ZOutTxt$(I)
  1137.                CALL TrimTrail(ZOutTxt$, " ")
  1138.                TxtLen = LEN(ZOutTxt$)
  1139.                SpacesToAdd = ZRightMargin - TxtLen
  1140.                IF SpacesToAdd > 0 THEN
  1141.                   '*
  1142.                   '* Skip leading spaces on the line
  1143.                   '*
  1144.                   Place = 1
  1145.                   IF LEFT$(ZOutTxt$, 1) = " " THEN
  1146.                      CALL FindWord(ZOutTxt$, 1, Place)
  1147.                   END IF
  1148.                   '*
  1149.                   '* Find all of the possible places to space out the line
  1150.                   '*
  1151.                   NumPlaces = 0
  1152.                   DO WHILE 1
  1153.                      CALL FindWord(ZOutTxt$, 1, Place)
  1154.                      IF Place < TxtLen THEN
  1155.                         NumPlaces = NumPlaces + 1
  1156.                         Places(NumPlaces) = Place
  1157.                      ELSE
  1158.                         EXIT DO
  1159.                      END IF
  1160.                   LOOP
  1161.                   '*
  1162.                   '* Fill in available places with soft spaces
  1163.                   '*
  1164.                   IF NumPlaces <> 0 THEN
  1165.                      ExtraPlaces = (SpacesToAdd MOD NumPlaces)
  1166.                      LeftExtra = ExtraPlaces \ 2
  1167.                      RightExtra = ExtraPlaces - LeftExtra
  1168.                      FOR J = NumPlaces TO 1 STEP -1
  1169.                         SpacesThisPlace = SpacesToAdd \ NumPlaces
  1170.                         IF J <= LeftExtra OR J > NumPlaces - RightExtra THEN
  1171.                            SpacesThisPlace = SpacesThisPlace + 1
  1172.                         END IF
  1173.                         IF SpacesThisPlace <> 0 THEN
  1174.                            ZOutTxt$ = LEFT$(ZOutTxt$, Places(J) - 1) + STRING$(SpacesThisPlace, SoftSpace$) + MID$(ZOutTxt$, Places(J))
  1175.                         END IF
  1176.                      NEXT J
  1177.                   END IF
  1178.                END IF
  1179.                ZOutTxt$(I) = ZOutTxt$
  1180.             END IF
  1181.          NEXT I
  1182.       END IF
  1183.  
  1184.       CALL UpdateScreen
  1185.  
  1186.       END SUB
  1187.  
  1188. '*  SaveCursor()
  1189. '*----------------------------------------------------------------------------
  1190. '*  This routine saves the current cursor position
  1191. '*
  1192. '*
  1193.       SUB SaveCursor (Row%, Col%) STATIC
  1194.       Row% = CurrentRow
  1195.       Col% = CurrentCol
  1196.       END SUB
  1197.  
  1198. '*  UnGetChar()
  1199. '*----------------------------------------------------------------------------
  1200. '*   Puts a key in the beginning of the keyboard buffer
  1201. '*
  1202. '*
  1203.       SUB UnGetChar (X) STATIC
  1204.       ZCommportStack$ = CHR$(X) + ZCommportStack$
  1205.       END SUB
  1206.  
  1207. '*  UnString()
  1208. '*----------------------------------------------------------------------------
  1209. '*  Removes one string from another
  1210. '*
  1211. '*
  1212.       SUB UnString (YY$, BadString$) STATIC
  1213.       I = INSTR(YY$, BadString$)
  1214.       WHILE I <> 0
  1215.          YY$ = LEFT$(YY$, I - 1) + MID$(YY$, I + LEN(BadString$))
  1216.          I = INSTR(YY$, BadString$)
  1217.       WEND
  1218.       END SUB
  1219.  
  1220. '*  UpdateScreen()
  1221. '*----------------------------------------------------------------------------
  1222. '*  This is one of the most important routines  It compares the arrays
  1223. '*  ZOutTxt$ and ZWorkAra$ and only sends the user the DIFFERENCE between the
  1224. '*  two within the viewing area  In this way all processing can be done on
  1225. '*  ZOutTxt$ and then the screen is updated to reflect the changes. After the
  1226. '*  users screen is updated, ZWorkAra$ is changed to reflect what should be
  1227. '*  on the users' screen The cursor is restored to its original position
  1228. '*
  1229. '*
  1230.       SUB UpdateScreen STATIC
  1231. 3100  CALL SaveCursor(RowSave, ColSave)
  1232.       FOR I = 3 TO 24
  1233.          Index = I + TopLine - 3
  1234.          ScreenLine$ = ZWorkAra$(I)
  1235.          MessageLine$ = ZOutTxt$(Index)
  1236.          LML = LEN(MessageLine$)
  1237.          IF Index = ZMaxMsgLines + 1 THEN
  1238.             CALL EraseToEOL(I, 1)
  1239.             CALL PutScreen("[* End of Message *]", CyanFore, ZFalse)
  1240.             ZWorkAra$(I) = CHR$(EndKey)
  1241.          ELSEIF Index > ZMaxMsgLines + 1 THEN
  1242.             IF ScreenLine$ <> BlankLine$ THEN
  1243.                CALL EraseToEOL(I, 1)
  1244.                ZWorkAra$(I) = BlankLine$
  1245.             END IF
  1246.          ELSEIF MessageLine$ = ScreenLine$ THEN
  1247.             '*
  1248.             '* Screen = What's in message buffer
  1249.             '*
  1250.          ELSEIF MessageLine$ = BlankLine$ OR MessageLine$ = SPACE$(LML) THEN
  1251.             CALL EraseToEOL(I, 1)
  1252.             ZWorkAra$(I) = MessageLine$
  1253.          ELSE
  1254.             CALL MoveCursor(I, 1)
  1255.             YY$ = MessageLine$
  1256.             CALL PutScreen(YY$, YellowFore, ZTrue)
  1257.             CALL EraseToEOL(CurrentRow, CurrentCol)
  1258.             ZWorkAra$(I) = ZOutTxt$(Index)
  1259.          END IF
  1260.       NEXT I
  1261.       CALL MoveCursor(RowSave, ColSave)
  1262.       END SUB
  1263.  
  1264. '*  UpdateStatusLine()
  1265. '*-----------------------------------------------------------------------------
  1266. '*  Rewrites the status line on screen line(s) 1 and 2
  1267. '*
  1268. '*    Input:  How% = 1   - Rewrite both lines
  1269. '*            How% = 2   - Just rewrite top line
  1270. '*
  1271.       SUB UpdateStatusLine (How%) STATIC
  1272. 3200  YY$ = "ANSIED " + Version$ + " by Tom Collins                       * Press ESC Twice for Menu *"
  1273.       YY$ = YY$ + SPACE$(79 - LEN(YY$))
  1274.       CALL MoveCursor(1, 1)
  1275.       CALL PutScreen(YY$, BlueFore, ZTrue)
  1276. 3210  IF How% = 1 THEN
  1277.          YY$ = CHR$(205) + " To: " + MsgTo$ + " " + CHR$(205) + " Re: " + MsgSubj$ + " " + CHR$(205)
  1278.          YY$ = YY$ + STRING$(79 - LEN(YY$), CHR$(205))
  1279.          IF InsertMode THEN
  1280.             MID$(YY$, 74) = " Ins "
  1281.          ELSE
  1282.             MID$(YY$, 74) = " Ovw "
  1283.          END IF
  1284.          I = 1
  1285.          CALL MoveCursor(2, I)
  1286.          CALL PutScreen(YY$, WhiteFore, ZFalse)
  1287.       END IF
  1288.       END SUB
  1289.  
  1290.